package com.ds.common.nacos;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;

@Configuration
@Slf4j
public abstract class NacosConfig<T extends ConfigModel> {

    @Autowired
    private ConfigService configService;

    private final AtomicReference<T> value = new AtomicReference<>();

    @PostConstruct
    public void init() throws NacosException {
        try {
            T object = parseConfig(configService.getConfigAndSignListener(getDataId(), getGroupId(), 3000, new Listener() {

                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    T object = parseConfig(configInfo);
                    if (object != null && object.isValid()) {
                        value.set(object);
                        onConfigRefresh(object);
                    }else {
                        log.error("config refresh error configInfo:{}",configInfo);
                    }
                }
            }));
            if(object!=null && object.isValid()) {
                value.set(object);
                onConfigRefresh(object);
            }
        } catch (Exception ex) {
            log.error("{}:{}", ex.getMessage(), getDataId(), ex);
        }
    }

    protected abstract String getDataId();

    protected abstract String getGroupId();

    protected  abstract Class<T> getClassType();
    protected boolean isUseDefaultValue() {
        return false;
    }

    /**
     * 配置刷新
     *
     * @param object
     */
    protected void onConfigRefresh(T object) {

    }

    protected T parseConfig(String configInfo) {
        try {
            return JSON.parseObject(configInfo, getClassType());
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            // 如果没有设置，这里使用默认值
            if(isUseDefaultValue()){
                try {
                    return getClassType().getDeclaredConstructor().newInstance();
                }catch (Throwable th){
                    log.error("parseConfig error",th);
                }
            }
            return null;
        }

    }

    public T getValue() {
        return value.get();
    }
}
